package cn.itcast.order.web;


import cn.itcast.feign.client.UserClient;
import cn.itcast.feign.pojo.User;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.service.OrderService;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

// @RefreshScope  // 第一种方式
@Slf4j
@Api(tags = {"订单接口"})
@RestController
@RequestMapping("order")
public class OrderController {

    @Resource
    private OrderService orderService;

    @Resource
    private RestTemplate restTemplate;

    // @Value("${pattern.dateformat}")
    // private String dateformat;

    @Resource
    private UserClient userClient;

    @ApiOperation("rest远程调用")
    @GetMapping("/rest/{orderId}")
    public Order queryOrderByUserIdWithRest(@PathVariable("orderId") Long orderId) {
        // 1.查询订单
        Order order = orderService.queryOrderById(orderId);
        // 2.利用RestTemplate发起http请求, 查询用户
        // 2.1.url路径
        String url = "http://user-service/user/" + order.getUserId();
        User user = restTemplate.getForObject(url, User.class);
        // 3.封装user到Order
        order.setUser(user);
        // 4.返回
        return order;
    }

    // 热点参数异常, 需要加上这个 @SentinelResource注解
    @SentinelResource("hot")
    @ApiOperation("feign远程调用")
    @GetMapping("/feign/{orderId}")
    public Order queryOrderByUserIdWithFeign(@PathVariable("orderId") Long orderId) {
        // 1.查询订单
        Order order = orderService.queryOrderById(orderId);
        // 2.利用Feign远程调用
        User user = userClient.findById(order.getUserId());
        // 3.封装user到Order
        order.setUser(user);
        // 4.返回
        return order;
    }


    /**
     * 需求:
     * 配置流控模式 -链路, 有查询订单[queryOrder]和创建订单业务[saveOrder],
     * 两者都需要查询商品, 针对从查询订单[web -> queryOrder]进入到查询商品[svc -> queryGoods]的请求统计, 并设置限流
     * 给queryGoods方法设置限流规则, 从/order/query进入queryGoods的方法显示QPS必须小于2
     * 实现:
     * 1.首先在service中给 queryGoods 方法加上一个@SentinelResource注解
     * 2.修改spring.cloud.sentinel.web-context-unify: false   # 关闭context整合
     * .    不然的话, 给资源名goods添加的链路模式的流控会失效
     * 3.给goods这个资源名添加链路模式的流控, 阈值为2, 入口资源为 /order/query
     */
    @ApiOperation("query查询")
    @GetMapping("/query")
    public String queryOrder() {
        // 查询商品
        orderService.queryGoods();
        // 查询订单
        log.info("================= 查询订单");
        return "查询订单成功";
    }


    @PostMapping("/save")
    public String saveOrder() {
        // 查询商品
        orderService.queryGoods();
        // 新增订单
        log.info("================= 新增订单");
        return "新增订单成功";
    }

    /**
     * 需求:
     * 配置流控规则 -关联, 当/order/update资源被访问的QPS超过5时, 对/order/query请求限流
     * 实现:
     * sentinel控制台中流控配置如下
     * 在接口 /order/query 配置流控规则 -> 流控模式选择关联 -> 关联资源为 /order/update
     */
    @ApiOperation("update更新")
    @PutMapping("/update")
    public String update() {
        return "更新订单成功";
    }


}
